#!/bin/bash
# Centos7 Rsync实时同步一键配置脚本
# 版本: 2.3
# 更新说明: 修复初始同步验证逻辑，优化状态检查
# 博客: https://blog.hx99.net
# 最后更新: 2025-04-28

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 全局变量
LOG_FILE="/var/log/inotify_rsync.log"
RSYNC_USER="rsync"
DEFAULT_PASSWORD="Backup@2023"

# 打印彩色欢迎信息
echo -e "${GREEN}"
echo "======================================================"
echo "      CentOS7 Rsync实时同步一键配置脚本 (inotify)     "
echo "======================================================"
echo -e "${NC}"
echo -e "${YELLOW}▌核心功能：${NC}"
echo -e "  ${GREEN}➤${NC} 全自动配置 ${BLUE}服务端${NC}(接收端)/${BLUE}客户端${NC}(发送端)"
echo -e "  ${GREEN}➤${NC} 基于inotify-tools实现文件变更实时监控"
echo -e "  ${GREEN}➤${NC} 自动创建systemd服务实现开机自启"
echo -e "  ${GREEN}➤${NC} 首次运行自动验证同步功能"
echo -e "  ${GREEN}➤${NC} 详细日志记录（${BLUE}${LOG_FILE}${NC}）"
echo -e "  ${GREEN}➤${NC} 完善的错误检测和自动重试机制"
echo ""
echo -e "${RED}▌重要提示：${NC}"
echo -e "  ${YELLOW}⚠${NC} 必须${RED}先配置服务端${NC}，再配置客户端"
echo -e "  ${YELLOW}⚠${NC} 确保防火墙放行${RED}873${NC}端口"
echo -e "  ${YELLOW}⚠${NC} 如输入的备份目录不存在，将自动创建"
echo -e "  ${YELLOW}⚠${NC} SELinux问题请执行：${GREEN}setsebool -P rsync_full_access on${NC}"
echo -e "  ${YELLOW}⚠${NC} 需${RED}root权限${NC}",适用于${RED}CentOS7${NC},其它系统未测试！
echo -e "${BLUE}▌技术支持：${NC}http://blog.hx99.net  https://gitee.com/cncsrf/rsync-remote-backup"
echo "============================================"
echo ""

# 检查root权限
USER_ID=$(id -u)
if [ "$USER_ID" -ne 0 ]; then
    echo -e "${RED}错误：请使用root用户运行此脚本！${NC}" >&2
    exit 1
fi

# 选择模式：服务端 or 客户端
echo -e "${BLUE}请选择配置模式：${NC}"
echo -e "1) 服务端（接收备份数据）"
echo -e "2) 客户端（发送备份数据）"
read -p "输入数字 (1/2): " MODE

# 验证模式输入
if [[ ! "$MODE" =~ ^[12]$ ]]; then
    echo -e "${RED}错误：请输入1或2！${NC}" >&2
    exit 1
fi

# 配置服务端 - 使用rsync-timed-backup-setup的服务端代码
if [ "$MODE" -eq 1 ]; then
    echo -e "${GREEN}正在配置Rsync服务端...${NC}"
    
    # 安装rsync
    if ! command -v rsync &> /dev/null; then
        echo -e "${BLUE}安装rsync...${NC}"
        yum install -y rsync || { echo -e "${RED}安装失败！${NC}"; exit 1; }
    fi

    # 输入备份目录
    read -p "请输入服务端备份存储目录 (默认: /opt/data_bak): " BACKUP_DIR
    BACKUP_DIR=${BACKUP_DIR:-/opt/data_bak}
    mkdir -p "$BACKUP_DIR" || { echo -e "${RED}目录创建失败！${NC}"; exit 1; }
    chmod 750 "$BACKUP_DIR"
    echo -e "${GREEN}备份目录已设置: ${BACKUP_DIR}${NC}"

    # 输入认证密码
    while true; do
        read -p "设置rsync认证密码 (默认: ${DEFAULT_PASSWORD}): " PASSWORD
        PASSWORD=${PASSWORD:-$DEFAULT_PASSWORD}
        
        # 密码复杂度检查
        if [ -z "$PASSWORD" ]; then
            echo -e "${RED}错误：密码不能为空！${NC}"
            continue
        fi
        if [ "${#PASSWORD}" -lt 4 ]; then
            echo -e "${YELLOW}警告：密码长度建议至少4位字符！继续？(y/n): ${NC}"
            read -p "" CONFIRM
            [[ "$CONFIRM" =~ ^[Yy]$ ]] || continue
        fi
        break
    done

    # 配置rsyncd.conf
    echo -e "${BLUE}生成 /etc/rsyncd.conf ...${NC}"
    cat > /etc/rsyncd.conf <<EOF
uid = root
gid = root
use chroot = no
max connections = 20
timeout = 300
pid file = /var/run/rsyncd.pid
log file = /var/log/rsyncd.log

[data_backup]
path = $BACKUP_DIR
comment = Backup Directory
read only = no
auth users = $RSYNC_USER
secrets file = /etc/rsyncd.secrets
EOF

    # 配置密码文件
    echo "$RSYNC_USER:$PASSWORD" > /etc/rsyncd.secrets
    chmod 600 /etc/rsyncd.secrets

    # 启动服务
    systemctl enable --now rsyncd
    systemctl status rsyncd --no-pager

    echo -e "${GREEN}服务端配置完成！${NC}"
    echo -e "${YELLOW}客户端连接命令示例：${NC}"
    echo -e "rsync -avz --delete /your/local/path/ ${RSYNC_USER}@$(hostname -I | awk '{print $1}')::data_backup --password-file=/etc/rsyncd.secrets"

# 配置客户端 - 保持原r3.sh的实时同步功能
else
    echo -e "${GREEN}正在配置Rsync客户端...${NC}"

    # 检查服务端是否已配置
    echo -e "${YELLOW}请确保服务端已提前配置完成！${NC}"
    read -p "按任意键继续..." -n 1 -r

    # 安装必要软件
    echo -e "${BLUE}安装EPEL源和必要软件...${NC}"
    if ! yum list installed epel-release &> /dev/null; then
        yum install -y epel-release || { echo -e "${RED}EPEL源安装失败！${NC}"; exit 1; }
    fi
    yum install -y rsync inotify-tools || { echo -e "${RED}软件安装失败！${NC}"; exit 1; }

    # 输入服务端IP
    while true; do
        read -p "请输入Rsync服务端IP地址: " SERVER_IP
        if [[ -z "$SERVER_IP" ]]; then
            echo -e "${RED}错误：IP地址不能为空！${NC}"
            continue
        fi
        if ! ping -c 1 "$SERVER_IP" &> /dev/null; then
            echo -e "${YELLOW}警告：无法ping通服务端IP，请检查网络！继续？(y/n): ${NC}"
            read -p "" CONFIRM
            [[ "$CONFIRM" =~ ^[Yy]$ ]] || continue
        fi
        break
    done

    # 固定模块名（不再询问用户输入）
    MODULE_NAME="data_backup"
    echo -e "${GREEN}使用默认模块名: ${MODULE_NAME}${NC}"

    # 输入本地监控目录（带默认值和自动创建）
    DEFAULT_LOCAL_DIR="/var/www"
    while true; do
        read -p "请输入需要监控的本地目录 (默认: ${DEFAULT_LOCAL_DIR}): " LOCAL_DIR
        LOCAL_DIR=${LOCAL_DIR:-$DEFAULT_LOCAL_DIR}
        
        if [ ! -d "$LOCAL_DIR" ]; then
            echo -e "${YELLOW}目录不存在，将自动创建 ${LOCAL_DIR} ...${NC}"
            mkdir -p "$LOCAL_DIR" || { 
                echo -e "${RED}目录创建失败！${NC}"
                echo -e "${YELLOW}是否尝试其他目录？(y/n): ${NC}"
                read -p "" CONFIRM
                [[ "$CONFIRM" =~ ^[Yy]$ ]] || exit 1
                continue
            }
            echo -e "${GREEN}已创建目录: ${LOCAL_DIR}${NC}"
            
            # 创建测试文件
            echo "This is a test file created by inotify rsync setup script" > "${LOCAL_DIR}/inotify_test_file.txt"
            echo -e "${GREEN}已创建测试文件：${LOCAL_DIR}/inotify_test_file.txt${NC}"
        fi
        break
    done

    # 输入密码
    read -p "输入服务端rsync密码 (默认: ${DEFAULT_PASSWORD}): " PASSWORD
    PASSWORD=${PASSWORD:-$DEFAULT_PASSWORD}
    echo "$PASSWORD" > /etc/rsyncd.secrets
    chmod 600 /etc/rsyncd.secrets

    # 生成实时同步脚本
    SYNC_SCRIPT="/opt/inotify_rsync.sh"
    echo -e "${BLUE}生成实时同步脚本 ${SYNC_SCRIPT} ...${NC}"

    cat > "$SYNC_SCRIPT" <<EOF
#!/bin/bash
# 监控目录
SRC_DIR="$LOCAL_DIR"
# 目标地址
DEST="${RSYNC_USER}@${SERVER_IP}::${MODULE_NAME}"
# 密码文件
PASS_FILE="/etc/rsyncd.secrets"
# 日志文件
LOG_FILE="$LOG_FILE"

# 检查必要组件是否存在
if ! command -v inotifywait &> /dev/null; then
    echo -e "\$(date +'%Y-%m-%d %H:%M:%S') [ERROR] inotifywait not found. Please install inotify-tools." | tee -a \${LOG_FILE}
    exit 1
fi

if ! command -v rsync &> /dev/null; then
    echo -e "\$(date +'%Y-%m-%d %H:%M:%S') [ERROR] rsync not found. Please install rsync." | tee -a \${LOG_FILE}
    exit 1
fi

# 检查目录是否存在
if [ ! -d "\${SRC_DIR}" ]; then
    echo -e "\$(date +'%Y-%m-%d %H:%M:%S') [ERROR] Source directory \${SRC_DIR} does not exist." | tee -a \${LOG_FILE}
    exit 1
fi

# 初始完整同步
echo -e "\$(date +'%Y-%m-%d %H:%M:%S') [INFO] 开始初始完整同步..." | tee -a \${LOG_FILE}
if rsync -avz --delete \${SRC_DIR}/ \${DEST} --password-file=\${PASS_FILE} >> \${LOG_FILE} 2>&1; then
    echo -e "\$(date +'%Y-%m-%d %H:%M:%S') [INFO] 初始同步成功" | tee -a \${LOG_FILE}
else
    echo -e "\$(date +'%Y-%m-%d %H:%M:%S') [ERROR] 初始同步失败 (错误码: \$?)" | tee -a \${LOG_FILE}
    exit 1
fi

# 启动inotify监控
echo -e "\$(date +'%Y-%m-%d %H:%M:%S') [INFO] 启动inotify监控..." | tee -a \${LOG_FILE}
/usr/bin/inotifywait -mrq --timefmt '%Y-%m-%d %H:%M' --format '%T %w%f %e' \\
-e modify,delete,create,attrib,move \${SRC_DIR} | while read file
do
    # 记录变更
    echo -e "\$(date +'%Y-%m-%d %H:%M:%S') [INFO] 检测到变更: \${file}" >> \${LOG_FILE}
    
    # 执行同步并添加错误处理
    if ! rsync -avz --delete \${SRC_DIR}/ \${DEST} --password-file=\${PASS_FILE} >> \${LOG_FILE} 2>&1; then
        echo -e "\$(date +'%Y-%m-%d %H:%M:%S') [ERROR] 同步失败" >> \${LOG_FILE}
        
        # 重试逻辑（修改为10次重试，每次间隔15秒）
        for i in {1..10}; do
            sleep 15
            echo -e "\$(date +'%Y-%m-%d %H:%M:%S') [INFO] 第\${i}次重试..." >> \${LOG_FILE}
            if rsync -avz --delete \${SRC_DIR}/ \${DEST} --password-file=\${PASS_FILE} >> \${LOG_FILE} 2>&1; then
                echo -e "\$(date +'%Y-%m-%d %H:%M:%S') [INFO] 重试成功" >> \${LOG_FILE}
                break
            fi
        done
        
        if [ \$i -eq 10 ]; then
            echo -e "\$(date +'%Y-%m-%d %H:%M:%S') [ERROR] 同步失败，已达最大重试次数" >> \${LOG_FILE}
            echo -e "\$(date +'%Y-%m-%d %H:%M:%S') [ERROR] 请检查服务端是否在线，恢复后执行: systemctl restart inotify_rsync" >> \${LOG_FILE}
        fi
    else
        echo -e "\$(date +'%Y-%m-%d %H:%M:%S') [INFO] 同步成功" >> \${LOG_FILE}
    fi
done

# 如果inotifywait意外退出
echo -e "\$(date +'%Y-%m-%d %H:%M:%S') [ERROR] inotifywait进程意外退出" >> \${LOG_FILE}
exit 1
EOF

    chmod +x "$SYNC_SCRIPT"

    # 创建systemd服务
    SERVICE_FILE="/etc/systemd/system/inotify_rsync.service"
    echo -e "${BLUE}创建systemd服务 ${SERVICE_FILE} ...${NC}"

    cat > "$SERVICE_FILE" <<EOF
[Unit]
Description=Inotify Rsync Service
After=network.target

[Service]
Type=simple
ExecStart=$SYNC_SCRIPT
Restart=always
RestartSec=5
User=root

[Install]
WantedBy=multi-user.target
EOF

    # 启动服务
    systemctl daemon-reload
    systemctl enable --now inotify_rsync

    # 检查服务状态
    echo -e "${GREEN}服务状态检查...${NC}"
    sleep 10  # 延长等待时间确保日志写入
    systemctl status inotify_rsync --no-pager

    # 验证初始同步（改进的验证逻辑）
    echo -e "${GREEN}验证初始同步...${NC}"
    if systemctl is-active --quiet inotify_rsync && 
       grep -q "初始同步成功" "$LOG_FILE"; then
        echo -e "${GREEN}实时同步服务配置完成！${NC}"
        echo -e "${YELLOW}监控目录: ${LOCAL_DIR}${NC}"
        echo -e "${YELLOW}目标服务端: ${RSYNC_USER}@${SERVER_IP}::${MODULE_NAME}${NC}"
        echo -e "${YELLOW}实时日志: ${LOG_FILE}${NC}"
        echo -e "${GREEN}服务管理命令:${NC}"
        echo -e "  启动服务: systemctl start inotify_rsync"
        echo -e "  停止服务: systemctl stop inotify_rsync"
        echo -e "  查看状态: systemctl status inotify_rsync"
        echo -e "  查看日志: journalctl -u inotify_rsync -f"
        
        # 显示同步成功的文件列表
        echo -e "\n${GREEN}已同步的文件列表：${NC}"
        grep -A 10 "sent" "$LOG_FILE" | grep -E "^\..*|^[^.]*$" | sed '/^$/d'
    else
        echo -e "${RED}初始同步失败，请检查日志: ${LOG_FILE}${NC}"
        echo -e "${YELLOW}可能原因：${NC}"
        echo "1. 服务端未运行"
        echo "2. 密码不正确"
        echo "3. 网络连接问题"
        exit 1
    fi
fi